/**
 @defgroup ACUAS_EP ACUAS Easy Programming
 @code #include "ACUAS.h" @endcode
 @brief C macros to easily program the ACUAS ATmega16/ATmega32 board. 
 @author Thomas Siepmann, Aachen University of Applied Sciences, Germany
 @see http://www.siepmann.fh-aachen.de
*/

/*@{*/
/// Processor speed (used for LCD lib)
#define XTAL  1000000L
#ifndef F_CPU
/// Processor speed (used for WAIT_SEC)
#define F_CPU 1000000UL
#endif
#include <avr/io.h>
#include <stdlib.h>

/** 
 *  @name  Program main structure
 */
/// Begin of instructions which are carried out only one time at the beginning of the program
#define PROGRAM_INIT   int main(){InitBoard(); 
/// Begin of instructions which are carried out in an endless loop.
#define PROGRAM_START  while(1){  
/// End of the program
#define PROGRAM_END	 } return 0;} 

/** 
 *  @name  Define Variables
 */
/// Declares a 32 bit integer variable with a range from - 2147483648 to + 2147483648
#define VARIABLE(v) signed long int v;
/// Declares a 16 bit unsigned variable with a range from 0 to 65535
#define VAR16(v) uint16_t v;
/// Declares a 8 bit unsigned variable with a range from 0 to 255
#define VAR(v) unsigned char v;
/// Declares a character array which can contain a string of max characters
#define STRING(s,max) char s[(max)+1];

/** 
 *  @name  Waiting
 */
/// Empty instruction. Continues immediately with the next instruction. Can be used for empty loops or before else conditions. Consumes no time.
#define DO_NOTHING ;
/// Waits x seconds. Range of x i from 0.1 to 25
#define WAIT_SEC(x) delay_ds(x*10);			

/** 
 *  @name  Random numbers
 */
/// Initialize the random generator. Must be invoked in the PROGRAM_INIT part. The seed is derived from the SRAM initial values at startup time.
#define RANDOM_INIT set_seed();
/**
 *  @brief   Generates a random number
 *  @param   n Minimal random value
 *  @param   m Maximal random value
 *  @return  random number between n and m (including)
 */
#define RANDOM(n,m)(n + random()%(m-n+1))

/** 
 *  @name  LEDs
 *  LED numbering is 1 based
 */
/// Switch on LED #n. Range of n is from 1 to 8. Example: LED_ON(3)
#define LED_ON(n) {(PORTC = PORTC & ~(1 << (n-1)));}
/// Switch off LED #n. Range of n is from 1 to 8. Example: LED_OFF(3)
#define LED_OFF(n) {(PORTC = PORTC | (1 << (n-1)));}
/// Use 8 LEDs to display a 8 bit binary value. LED 1 represents the LSB. Example: DISPLAY_LEDS(0b10101010) or DISPLAY_LEDS(216)
#define DISPLAY_LEDS(v) PORTC = (~((unsigned char)v));

/** 
 *  @name  Buttons and joystick
 *  Button numbering is 1 based
 */
/// Execute the following instruction if the button is pressed
#define ON_BUTTON(n) if(!(PINA & (1 << (n-1))))
/// Execute the following instruction if the button is not pressed
#define OFF_BUTTON(n)  if(PINA & (1 << (n-1)))
/// Wait until button is pressed
#define WAIT_FOR_BUTTON(n) while(PINA & (1 << (n-1)));
/// Wait until button is released
#define WAIT_FOR_RELEASE_BUTTON(n) while(!(PINA & (1 << (n-1))));
/** 
 *  @name  Joystick up
 */
///Execute the following instruction if the joystick up button is pressed
#define ON_JOYSTICK_UP     if(!(PINA & (1 << 6)))
///Execute the following instruction if the joystick up button is not pressed
#define OFF_JOYSTICK_UP      if(PINA & (1 << 6))
///Wait until the joystick up button is pressed
#define WAIT_FOR_JOYSTICK_UP while(PINA & (1 << 6));
///Wait until the joystick up button is released
#define WAIT_FOR_RELEASE_JOYSTICK_UP while(!(PINA & (1 << 6)));
/** 
 *  @name  Joystick down
 */
///Execute the following instruction if the joystick down button is pressed
#define ON_JOYSTICK_DOWN   if(!(PINA & (1 << 4)))
///Execute the following instruction if the joystick down button is not pressed
#define OFF_JOYSTICK_DOWN    if(PINA & (1 << 4))
///Wait until the joystick down button is pressed
#define WAIT_FOR_JOYSTICK_DOWN while(PINA & (1 << 4));
///Wait until the joystick down button is released
#define WAIT_FOR_RELEASE_JOYSTICK_DOWN while(!(PINA & (1 << 4)));
/** 
 *  @name  Joystick right
 */
///Execute the following instruction if the joystick right button is pressed
#define ON_JOYSTICK_RIGHT  if(!(PINA & (1 << 5)))
///Execute the following instruction if the joystick right button is not pressed
#define OFF_JOYSTICK_RIGHT   if(PINA & (1 << 5))
///Wait until the joystick right button is pressed
#define WAIT_FOR_JOYSTICK_RIGHT while(PINA & (1 << 5));
///Wait until the joystick right button is released
#define WAIT_FOR_RELEASE_JOYSTICK_RIGHT while(!(PINA & (1 << 5)));
/** 
 *  @name  Joystick left
 */
///Execute the following instruction if the joystick left button is pressed
#define ON_JOYSTICK_LEFT   if(!(PINA & (1 << 7)))
///Execute the following instruction if the joystick left button is not pressed
#define OFF_JOYSTICK_LEFT    if(PINA & (1 << 7))
///Wait until the joystick left button is pressed
#define WAIT_FOR_JOYSTICK_LEFT while(PINA & (1 << 7));
///Wait until the joystick left button is released
#define WAIT_FOR_RELEASE_JOYSTICK_LEFT while(!(PINA & (1 << 7)));

/** 
 *  @name  AD converter
 *  Channel numbering is 1 based!
 */
  /// Activate ADC with Prescaler 16 --> 1Mhz/16 = 62.5kHz. ADEN=AD enable, ADPS2 AD preselector divisor 16. Reference voltage = AVCC
#define ACTIVATE_ADC  {ADCSRA = (1<<ADEN) | (1<<ADPS2); ADMUX |= (0<<REFS1) | (1<<REFS0);}
  /// Select channel. Channel numbering is 1 based
#define ADC_CHANNEL(ch) ADMUX &= 0b11110000; ADMUX |= (ch-1); PORTA &= ~(1 << (ch-1));
  /// ADSC = ADC Start Conversion. Wait until conversion completed
#define START_ADC {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);}
/// Start a 10 bit AD conversion and store the value in a 8 bit variable
#define ADCONVERTlow(vc) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);vc=ADCW >> 2;}
/// Start a 10 bit AD conversion and store the digital value in a 16 bit variable
#define ADCONVERT(x) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);x=ADCW;}
/// Start a 10 bit AD conversion and store the result in mV in an integer (or double or float) variable
#define ADCONVERT_MV(x) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);x=ADCW*5./1.024;}


/** 
 *  Set simulation modus: no waiting (WAIT_SEC) and constant random seed (for testing). Must be the first line in .c file.
 *         #define SIMULATION
 */

// FUNCTIONS
#include "ACUAS.c"

/*@}*/
